#include "mbed.h"
#include "max31865.h"
#include "pid.h"

//------------------------------------
// Hyperterminal configuration
// 9600 bauds, 8-bit data, no parity
//------------------------------------
PwmOut mypwm3(PC_9);//PC_9
PwmOut mypwm1(PA_15);//PC_9
PwmOut mypwm2(PB_7);//PC_9
Serial pc(SERIAL_TX, SERIAL_RX);

DigitalOut mypin(PC_0);
DigitalOut mosfet_ctrl(PC_8);


const unsigned int temp_adc_code[46]={
        1517,       2394,       3254,       4101,       4936,       5762,       6579,       6903,       7227,       7550,
//  -200        -175        -150        -125        -100        -75         -50         -40         -30         -20     
        7871,       8192,       8512,       8830,       9148,       9465,       9781,       10096,  10410,  10723,
//  -10         0               10          20          30          40          50          60          70          80
        11035,  11346,  11657,  11966,  12274,  12582,  12888,  13194,  13498,  13802,
//  90          100         110         120         130         140         150         160         170         180
        14104,  14406,  15156,  15901,  16639,  17371,  18098,  18818,  19533,  20242,
//  190         200         225         250         275         300         325         350         375         400
        20945,  21642,  22333,  23018,  23697,  24370
//  425         450         475         500         525         550
};

unsigned char bottom=0,top=46;
int order_to_temp(int order_number)  //ÐòºÅ×ª³ÉÎÂ¶È
{
        int t;
        switch(order_number)
        {
            case 0: t=-200;break;
            case 1: t=-175;break;
            case 2: t=-150;break;
            case 3: t=-125;break;
            case 4: t=-100;break;
            case 5: t=-75;break;
            case 6: t=-50;break;
            case 7: t=-40;break;
            case 8: t=-30;break;
            case 9: t=-20;break;
            case 10: t=-10;break;
            case 11: t=0;break;
            case 12: t=10;break;
            case 13: t=20;break;
            case 14: t=30;break;
            case 15: t=40;break;
            case 16: t=50;break;
            case 17: t=60;break;
            case 18: t=70;break;
            case 19: t=80;break;
            case 20: t=90;break;
            case 21: t=100;break;
            case 22: t=110;break;
            case 23: t=120;break;
            case 24: t=130;break;
            case 25: t=140;break;
            case 26: t=150;break;           
            case 27: t=160;break;
            case 28: t=170;break;
            case 29: t=180;break;
            case 30: t=190;break;           
            case 31: t=200;break;
            case 32: t=225;break;
            case 33: t=250;break;
            case 34: t=275;break;
            case 35: t=300;break;
            case 36: t=325;break;
            case 37: t=350;break;           
            case 38: t=375;break;
            case 39: t=400;break;
            case 40: t=425;break;
            case 41: t=450;break;               
            case 42: t=475;break;
            case 43: t=500;break;           
            case 44: t=525;break;
            case 45: t=550;break;           
        
        }
        return t;
}
    


double compute_temp(unsigned int adc_code,unsigned int bottom,unsigned int top)
{
    int t_top,t_bottom;
    double a,b,t_current_buf;
    if((top-bottom)/2==0)
    {
			t_top=order_to_temp(top);   //top ¶ÔÓ¦µÄÎÂ¶È
      t_bottom=order_to_temp(bottom); //bottom ¶ÔÓ¦µÄÎÂ¶È
      a=(t_top-t_bottom)/(double)(temp_adc_code[top]-temp_adc_code[bottom]); //a=(t1-t2)/(x1-x2)
      b=t_top-a*temp_adc_code[top];
      t_current_buf=a*adc_code+b;  //y=ax+b
      return t_current_buf;
    }
    else if(adc_code<=temp_adc_code[(top-bottom)/2+bottom])
    {
        t_current_buf=compute_temp(adc_code,bottom,(top-bottom)/2+bottom);
    }else if(adc_code>temp_adc_code[(top-bottom)/2+bottom])
    {
        t_current_buf=compute_temp(adc_code,(top-bottom)/2+bottom,top);
    }
    return t_current_buf;
}


void setPWM(char chx,float Pwm)
{
	int pulse;
	pulse = Pwm * 10000;
	switch(chx)
	{
		case 1:mypwm1.pulsewidth_us(pulse);	break;
		case 2:mypwm2.pulsewidth_us(pulse);	break;
		case 3:mypwm3.pulsewidth_us(pulse);	break;
	}
}

float getTemp(char chx)
{
	return ((double)(compute_temp((max31865_read_data(chx,0x01)<<7)+(max31865_read_data(chx,0x02)>>1),0,46)));
}

unsigned int max31865_adc_code;
int t_pulsewidth=10,t_period=10,t_best_pulsewidth;
double t_current;

	struct _PID{
	double Error0;
	double Error1;
	double Error2;
	double Pwm0;
	double Pwm1;
	double PidP;
	double PidI;
	double PidD;
	double SetT;
	char Channel;
	};
struct _PID spid1,spid2,spid3;
	
void PIDInit(void)
{
  spid1.Error0=0;
	spid1.Error1=0;
	spid1.Error2=0;
	spid1.Pwm0=0;
	spid1.Pwm1=0;
	spid1.PidP=0.03;
	spid1.PidI=0.0002;
	spid1.PidD=0.00001;
	spid1.SetT=120;
	spid1.Channel=1;
	
  spid2.Error0=0;
	spid2.Error1=0;
	spid2.Error2=0;
	spid2.Pwm0=0;
	spid2.Pwm1=0;
	spid2.PidP=0.07;
	spid2.PidI=0.001;
	spid2.PidD=0;
	spid2.SetT=111;
	spid2.Channel=2;	
	
  spid3.Error0=0;
	spid3.Error1=0;
	spid3.Error2=0;
	spid3.Pwm0=0;
	spid3.Pwm1=0;
	spid3.PidP=0.07;
	spid3.PidI=0.001;
	spid3.PidD=0;
	spid3.SetT=118;
	spid3.Channel=3;
}
float PIDCtrl(struct _PID *spid)	
{	
	double cTemp=0;
	cTemp=getTemp(spid->Channel);
	spid->Error0 = spid->SetT - cTemp;
//	pc.printf("current_temp1 %f\r\n", cTemp);	
//	pc.printf("current_temp1 %f\r\n", cTemp);
	
	switch(spid->Channel)
	{
		case 1:	pc.printf("current_temp1 %f\r\n", cTemp);
						break;
		case 2:	pc.printf("current_temp2 %f\r\n", cTemp);
						break;
		case 3:	pc.printf("current_temp3 %f\r\n", cTemp);	
						break;
	}	
	//spid->Pwm0	 = spid->Pwm1 + (spid->PidP + spid->PidI)* spid->Error0 - spid->PidP * spid->Error1;
	//Pwm0	 = Pwm1 + (PidP + PidI+PidD)* Error0 -(PidP + 2*PidD)* Error1+ PidD*Error2;
	spid->Pwm0	 = spid->Pwm1 + (spid->PidP + spid->PidI+ spid->PidD)* spid->Error0 - (spid->PidP+spid->PidD*2) * spid->Error1+spid->PidD*spid->Error2;
	spid->Error1 = spid->Error0;
	spid->Error2 = spid->Error1;			
	if(spid->Pwm0 >1)
		spid->Pwm0 =1;
	else if (spid->Pwm0 <0)
		spid->Pwm0 = 0;		
	spid->Pwm1 = spid->Pwm0;
	setPWM(spid->Channel,spid->Pwm1);
	return spid->Pwm1;
}

int main() 
{
  unsigned char temp_set;
  long i = 1;
  unsigned int temp_buf,temp_adc_code;
	double pulse_buf;
//	double PidP, PidI, SetT;
//	double Error0, Error1, Error2;
//	double Pwm0, Pwm1;
  max31865_init();
  max31865_write_data(1,0x80,0x00);         //Auto Mode, 3-Wire, 50Hz
	wait_ms(70);
  max31865_write_data(3,0x80,0x00);         //Auto Mode, 3-Wire, 50Hz
	wait_ms(70);
	max31865_write_data(2,0x80,0x00);         //Auto Mode, 3-Wire, 50Hz
  wait_ms(70);
  max31865_write_data(1,0x80,0xd1);         //Auto Mode, 3-Wire, 50Hz
	wait_ms(70);
  max31865_write_data(3,0x80,0xd1);         //Auto Mode, 3-Wire, 50Hz
	wait_ms(70);
	max31865_write_data(2,0x80,0xd1);         //Auto Mode, 3-Wire, 50Hz
  wait_ms(70);
	mypwm1.period_us(10000);
	mypwm2.period_us(10000);
	mypwm3.period_us(10000);
	PIDInit();

  while(1) 
  {

		PIDCtrl(&spid1);
		PIDCtrl(&spid2);
		PIDCtrl(&spid3);

		wait_ms(100);
	}
}
 